package admin.core.ui;

import admin.core.annotation.TableId;
import admin.core.enums.IdType;
import admin.core.mapper.BaseMapper;
import admin.core.page.Page;
import admin.core.service.IService;
import admin.core.service.ServiceImpl;
import admin.core.utils.AnnotationUtils;
import admin.core.utils.TypeUtils;

import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class GenericTableFrame<E, S extends ServiceImpl<BaseMapper<E>, E>> extends JFrame {
    private final Class<E> entityClass;
    private final S service;

    private static final Integer INPUT_WIDTH = 150;
    private static final Integer INPUT_HEIGHT = 27;
    private static final Integer TABLE_ROW_HEIGHT = 30;


    private JTable table;
    private DefaultTableModel model;

    private final JTextField searchField = new JTextField();
    private final JLabel pageNumLabel = new JLabel();
    private final JLabel totalPageLabel = new JLabel();

    public GenericTableFrame(IService<E> service) {
        this.service = (S) service;
        this.entityClass = ((ServiceImpl<BaseMapper<E>, E>) service).getEntityClass();
        this.setTitle(AnnotationUtils.getTableName(entityClass) + "管理系统");
        this.setSize(800, 600);
        this.setResizable(false);
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);

        initComponents();

        setVisible(true);
    }

    private void initComponents() {
        JPanel searchPanel = new JPanel();

        searchField.setPreferredSize(new Dimension(INPUT_WIDTH, INPUT_HEIGHT));
        JButton searchButton = new JButton("查询");
        JButton createButton = new JButton("新增");

        // 添加查询按钮监听器
        searchButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Page<E> page = search(1);
                refreshData(page);
            }
        });
        createButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                showCreateDialog();
            }
        });

        searchPanel.add(searchField);
        searchPanel.add(searchButton);
        searchPanel.add(createButton);

        // 初始化表格
        initTable();

        JPanel paginationPanel = createPaginationPanel();

        // 设置布局
        setLayout(new BorderLayout());
        add(searchPanel, BorderLayout.NORTH);
        add(new JScrollPane(table), BorderLayout.CENTER);
        add(paginationPanel, BorderLayout.SOUTH);
    }


    private JPanel createPaginationPanel() {
        JPanel panel = new JPanel();
        JButton preBtn = new JButton("<");
        JLabel label = new JLabel("/");
        JButton nextBtn = new JButton(">");

        preBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int pageNum = Integer.parseInt(pageNumLabel.getText().trim());
                pageNum = Math.max(pageNum - 1, 1);
                Page<E> page = search(pageNum);
                refreshData(page);
            }
        });
        nextBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int pageNum = Integer.parseInt(pageNumLabel.getText().trim());
                int totalPage = Integer.parseInt(totalPageLabel.getText().trim());
                pageNum = Math.min(pageNum + 1, totalPage);
                Page<E> page = search(pageNum);
                refreshData(page);
            }
        });


        panel.add(preBtn);
        panel.add(pageNumLabel);
        panel.add(label);
        panel.add(totalPageLabel);
        panel.add(nextBtn);
        return panel;
    }

    private void showCreateDialog() {
        GenericDialog dialog = new GenericDialog(this, null);
        dialog.setVisible(true);
    }

    private void initTable() {
        List<String> columnNames = AnnotationUtils.getColumnNames(entityClass);
        columnNames.add("操作"); // 新增一列用于放置“查看”按钮

        model = new DefaultTableModel(columnNames.toArray(new String[0]), 0);

        table = new JTable(model) {
            // 禁用单元格编辑
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };
        table.setRowHeight(TABLE_ROW_HEIGHT);

        // 居中
        DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
        centerRenderer.setHorizontalAlignment(JLabel.CENTER);
        for (int i = 0; i < table.getColumnCount(); i++) {
            table.getColumnModel().getColumn(i).setCellRenderer(centerRenderer);
        }


        // 为“查看”按钮添加点击事件处理
        table.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                if (table.getSelectedColumn() == AnnotationUtils.getAnnotatedFields(entityClass).size()) {
                    Field idField = AnnotationUtils.getIdField(entityClass);
                    assert idField != null;
                    Class<?> idFieldType = idField.getType();
                    Object idValue = model.getValueAt(table.getSelectedRow(), 0);
                    Object id = TypeUtils.convertIdType(idValue, idFieldType);
                    E item = service.getById(id);
                    showDetails(item);
                }

            }
        });

        table.getTableHeader().setReorderingAllowed(false);
        refreshData(service.list(1, 10));
    }

    private Page<E> search(Integer pageNum) {
        String searchTerm = searchField.getText().trim();
        return searchTerm.isEmpty() ? service.list(pageNum, 10) : service.list(searchTerm, pageNum, 10);
    }

    private void refreshData(Page<E> page) {
        refreshTableData(page.getList());
        refreshPagination(page.getPageNum(), page.getPageSize(), page.getTotal());
    }

    private void refreshTableData(List<E> data) {
        model.setRowCount(0);

        for (E item : data) {
            Object[] rowData = AnnotationUtils.getRowData(item, entityClass.getDeclaredFields());
            model.addRow(rowData);
        }
    }

    private void refreshPagination(Integer pageNum, Integer pageSize, Integer total) {
        pageNumLabel.setText(String.valueOf(pageNum));
        totalPageLabel.setText(String.valueOf(total % pageSize == 0 ? total / pageSize : total / pageSize + 1));
    }

    private void showDetails(E entity) {
        GenericDialog dialog = new GenericDialog(this, entity);
        dialog.setVisible(true);
    }


    private class GenericDialog extends JDialog {
        private static final String OPERATE_UPDATE = "u";
        private static final String OPERATE_INSERT = "i";

        private String op = OPERATE_UPDATE;
        private final E entity;
        private final Map<String, JTextField> inputFields = new HashMap<>();

        public GenericDialog(JFrame owner, E entity) {
            super(owner, true);
            if (entity == null) {
                op = OPERATE_INSERT;
                try {
                    Constructor<E> constructor = entityClass.getDeclaredConstructor();
                    entity = constructor.newInstance();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            this.entity = entity;
            initUI();
        }

        private void initUI() {
            setLayout(new BorderLayout());

            JPanel detailsPanel = createEditableDetailsPanel();
            add(detailsPanel, BorderLayout.CENTER);

            JPanel buttonPanel = createButtonPanel();
            // 设置按钮面板与对话框底部之间的距离
            buttonPanel.setBorder(BorderFactory.createEmptyBorder(5, 100, 10, 100)); // 上 左 下 右
            add(buttonPanel, BorderLayout.SOUTH);

            pack();
            setLocationRelativeTo(getOwner());
        }

        private JPanel createEditableDetailsPanel() {
            JPanel panel = new JPanel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.insets = new Insets(5, 5, 5, 5); // 组件之间的内边距

            List<Field> fields = AnnotationUtils.getAnnotatedFields(entityClass);
            int row = 0;

            for (Field field : fields) {
                try {
                    field.setAccessible(true);
                    String labelName = AnnotationUtils.getLabelName(field);
                    Object value = field.get(entity);

                    IdType idType = AnnotationUtils.getIdType(entityClass);
                    if (field.isAnnotationPresent(TableId.class) && op.equals("i") && idType == IdType.AUTO) {
                        continue;
                    }

                    JLabel label = new JLabel(labelName + ": ");
                    JTextField textField = new JTextField(value == null ? "" : value.toString(), 20);
                    inputFields.put(field.getName(), textField); // 保存字段名和对应的输入框
                    textField.setPreferredSize(new Dimension(INPUT_WIDTH, INPUT_HEIGHT));

                    if (field.isAnnotationPresent(TableId.class) && op.equals("u")) {
                        textField.setEditable(false);
                    }

                    // 添加标签到面板
                    gbc.gridx = 0; // 第一列
                    gbc.gridy = row; // 当前行
                    gbc.anchor = GridBagConstraints.EAST; // 标签靠右对齐
                    gbc.fill = GridBagConstraints.NONE;
                    gbc.weightx = 0.0; // 不允许扩展
                    panel.add(label, gbc);

                    // 添加文本字段到面板
                    gbc.gridx = 1; // 第二列
                    gbc.gridy = row; // 同一行
                    gbc.anchor = GridBagConstraints.WEST; // 文本字段靠左对齐
                    gbc.fill = GridBagConstraints.HORIZONTAL; // 水平填充
                    gbc.weightx = 1.0; // 允许扩展
                    panel.add(textField, gbc);

                    row++;
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

            return panel;
        }

        private JPanel createButtonPanel() {
            JPanel panel = new JPanel();
            panel.setLayout(new GridBagLayout()); // 使用 GridBagLayout 实现居中
            GridBagConstraints gbc = new GridBagConstraints();

            JButton saveButton = new JButton("保存");
            JButton deleteButton = new JButton("删除");

            // 设置按钮之间的间距
            gbc.insets = new Insets(5, 5, 5, 5); // 上 左 下 右

            // 添加保存按钮
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.CENTER; // 按钮居中对齐
            gbc.weightx = 0.5; // 平均分配水平空间
            gbc.fill = GridBagConstraints.NONE;
            panel.add(saveButton, gbc);

            // 添加删除按钮，并在它左边留出一些空间
            gbc.gridx = 1;
            gbc.insets = new Insets(5, 20, 5, 5); // 在左侧增加额外的间距
            if (op.equals(OPERATE_UPDATE)) {
                panel.add(deleteButton, gbc);
            }

            saveButton.addActionListener(e -> onSaveButtonClick());
            deleteButton.addActionListener(e -> onDeleteButtonClick());

            return panel;
        }

        private void onSaveButtonClick() {
            try {
                for (Map.Entry<String, JTextField> entry : inputFields.entrySet()) {
                    Field field = entityClass.getDeclaredField(entry.getKey());
                    field.setAccessible(true);
                    field.set(entity, TypeUtils.convertStringType(entry.getValue().getText(), field.getType()));
                }
                if (op.equals(OPERATE_UPDATE)) {

                    service.updateById(entity);
                } else {
                    service.save(entity);
                }
                refreshData(service.list(1, 10));
                dispose();
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, "保存失败: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
            }
        }

        private void onDeleteButtonClick() {
            int confirm = JOptionPane.showConfirmDialog(this,
                    "确定要删除吗？", "确认删除",
                    JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
            if (confirm == JOptionPane.YES_OPTION) {
                try {
                    Field idField = AnnotationUtils.getIdField(entityClass);
                    assert idField != null;
                    idField.setAccessible(true);
                    Object value = idField.get(entity);
                    service.deleteById(value.toString());
                    refreshData(service.list(1, 10));
                    dispose();
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(this, "删除失败: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
                }
            }
        }


    }


    private S createService(Class<S> serviceClass) throws Exception {
        Constructor<S> constructor = serviceClass.getDeclaredConstructor();
        return constructor.newInstance();
    }
}